package com.yc.resfoods.filters;

import com.yc.resfoods.config.JwtTokenUtil;
import com.yc.resfoods.service.JwtUserDetailsService;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName JwtRequestsFilter
 * @since: 2023/8/21 14:57
 * @auth: kirito
 * @description:
 * 对于任何传入的请求 都会执行filter类 检查请求是否具有有效的jwt令牌
 * 如果它具有有效的jwt令牌 则在上下文中设置身份验证 以指定当前用户已通过身份验证
 **/
@Component
@Slf4j
public class JwtRequestsFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final String requestTokenHeader = request.getHeader("Authorization");
        String username = null;
        String jwtToken = null;
        //jwt token 以bearer token值形式提供  移除bearer 得到token
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                System.out.println("unable to get jwt token");
            } catch (ExpiredJwtException e) {
                System.out.println("jwt token has expired");
            }
        }else {
            logger.warn("jwt token does not begin with bearer string");
        }
        //判断用户名
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            //根据用户名获取信息  权限
            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
            /*jwtToken是用户传过来的  userDetails是根据用户名从数据库查询出来的  标准的
            * 重新用 HS256(userDetails，secret)计算得到string，与jwtToken比较 是否相等*/
            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                //在上下文中设置身份验证后 我们指定当前用户已通过身份验证  所以它通过了spring安全配置成功
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(request,response);

    }
}
